#include"types.h"
#ifndef __ASSEMBLER__
//读取CPU的hart_id
//但是对于单CPU好像没啥卵用
static inline uint64 r_mhartid(){
  uint64 x;
  asm volatile("csrr %0, mhartid" : "=r" (x) );
  return x;
}

//读写机器模式的状态寄存器
static inline uint64 r_mstatus(){
  uint64 x;
  asm volatile("csrr %0, mstatus" : "=r" (x) );
  return x;
}

static inline void  w_mstatus(uint64 x){
  asm volatile("csrw mstatus, %0" : : "r" (x));
}

static inline uint64 r_sstatus()
{
  uint64 x;
  asm volatile("csrr %0, sstatus" : "=r" (x) );
  return x;
}

static inline void w_sstatus(uint64 x){
  asm volatile("csrw sstatus, %0" : : "r" (x));
}
//读写m-mode的返回地址
static inline uint64 r_mepc() {
    uint64 x;
    asm volatile("csrr %0, mepc" : "=r" (x) );
    return x;
}


static inline void w_mepc(uint64 x) {
    asm volatile("csrw mepc, %0" : : "r" (x));
}
//将用户的进程的起始位置放入sepc寄存器中
static inline void w_sepc(uint64 x)
{
  asm volatile("csrw sepc, %0" : : "r" (x));
}

static inline void w_satp(uint64 x){
  asm volatile("csrw satp, %0" : : "r" (x));
}

//委托异常处理
static inline uint64 r_medeleg()
{
  uint64 x;
  asm volatile("csrr %0, medeleg" : "=r" (x) );
  return x;
}

static inline void w_medeleg(uint64 x)
{
  asm volatile("csrw medeleg, %0" : : "r" (x));
}

// 委托中断处理
static inline uint64 r_mideleg()
{
  uint64 x;
  asm volatile("csrr %0, mideleg" : "=r" (x) );
  return x;
}

static inline void w_mideleg(uint64 x)
{
  asm volatile("csrw mideleg, %0" : : "r" (x));
}

//中断使能寄存器
//用于处理哪些中断归s-mode管理
//外部中断，时间中断，软件中断

static inline void w_pmpcfg0(uint64 x)
{
  asm volatile("csrw pmpcfg0, %0" : : "r" (x));
}

static inline void w_pmpaddr0(uint64 x)
{
  asm volatile("csrw pmpaddr0, %0" : : "r" (x));
}

static inline uint64 r_sie()
{
  uint64 x;
  asm volatile("csrr %0, sie" : "=r" (x) );
  return x;
}

static inline void w_sie(uint64 x)
{
  asm volatile("csrw sie, %0" : : "r" (x));
}

static inline uint64 r_mie()
{
  uint64 x;
  asm volatile("csrr %0, mie" : "=r" (x) );
  return x;
}

static inline void w_mie(uint64 x)
{
  asm volatile("csrw mie, %0" : : "r" (x));
}

static inline uint64 r_time()
{
  uint64 x;
  asm volatile("csrr %0, time" : "=r" (x) );
  return x;
}

static inline void w_stimecmp(uint64 x)
{
  // asm volatile("csrw stimecmp, %0" : : "r" (x));
  asm volatile("csrw 0x14d, %0" : : "r" (x));
}

static inline void w_tp(uint64 x)
{
  asm volatile("mv tp, %0" : : "r" (x));
}

// Supervisor Trap-Vector Base Address
// low two bits are mode.
static inline void w_stvec(uint64 x)
{
  asm volatile("csrw stvec, %0" : : "r" (x));
}

static inline uint64 r_stvec()
{
  uint64 x;
  asm volatile("csrr %0, stvec" : "=r" (x) );
  return x;
}

static inline void w_sscratch(uint64 val) {
  asm volatile("csrw sscratch, %0" : : "r"(val));
}

#define SSTATUS_SPP (1L << 8)  // Previous mode, 1=Supervisor, 0=User
#define SSTATUS_SPIE (1L << 5) // Supervisor Previous Interrupt Enable
#define SSTATUS_UPIE (1L << 4) // User Previous Interrupt Enable
#define SSTATUS_SIE (1L << 1)  // Supervisor Interrupt Enable
#define SSTATUS_UIE (1L << 0)  // User Interrupt Enable

#define MSTATUS_MPP_MASK (3L << 11) // 11左移到11,12Bit处，即0b110000000000
#define MSTATUS_MPP_M (3L << 11)
#define MSTATUS_MPP_S (1L << 11)
#define MSTATUS_MPP_U (0L << 11)
#define MSTATUS_MIE (1L << 3)    // machine-mode interrupt enable.

//外部中断，时间中断，软件中断，全部交给supervise mode进行处理
#define SIE_SEIE (1L << 9) // external
#define SIE_STIE (1L << 5) // timer
#define SIE_SSIE (1L << 1) // software

#define MIE_STIE (1L << 5)  // supervisor timer

#endif